
#include <BStyle>
#include <BOpenGL>
#include <BPainter>
#include <BThread>
#include <BClock>
#include <BButton>
#include <BMouseEvent>
#include <BEvent>
#include <BChangeEvent>
#include <BApplication>
#include <BSystem>
#include <BScreen>
#include <BMainWindow>
#include "member_BMainWindow.h"
#include "member_BWidget.h"
#include "IWindow.h"

#define member						(*(member_BMainWindow*)_ptr)
#define member_allocate()			_ptr = new member_BMainWindow(this)
#define member_release()			delete (member_BMainWindow*)_ptr

using namespace BWE;

BMainWindow::BMainWindow(const BString& title)
{
	member_allocate();
	this->setPerchs(0, 22, 0, 0);
	this->setBorder(5);
	this->setTitle(title);

	int number = BSystem::GetScreenNumber();
	const BScreen* screen = BSystem::GetScreen(0);
	BRect screenRect(screen->size());
	BRect rect = screenRect.align(Align_Center, screen->size() * 0.76);
	this->setRect(rect);
}
BMainWindow::~BMainWindow()
{
	member_release();
}

void BMainWindow::close()
{
	BApplication::done();
}

void BMainWindow::setTitleIcon(BIcon* titleIcon)
{
	if (member.titleIcon != titleIcon)
	{
		member.titleIcon = titleIcon;
		member.dirty = true;
		this->fresh();
	}
}
BIcon* BMainWindow::titleIcon() const
{
	return member.titleIcon;
}

void BMainWindow::setTitleAlign(Align align)
{
	if (member.titleAlign != align)
	{
		member.titleAlign = align;
		member.dirty = true;
		this->fresh();
	}
}
Align BMainWindow::titleAlign() const
{
	return member.titleAlign;
}

void BMainWindow::changeEvent(const BChangeEvent& event)
{
	if (event.change() == Change_Title)
	{
		member.dirty = true;
		this->fresh();
	}
	if (event.change() == Change_Style)
	{
		const BStyle* style = this->realStyle();
		const BFont* font = style->font();
		if (font)
		{
			int fontHeight = font->height();
			int top = this->perch(Part_Top);
			if (top < fontHeight)
			{
				this->setPerch(Part_Top, fontHeight);
			}
		}

		const BValue& buttonSizeValue = style->value(Value_Title_Button_Size);
		if (buttonSizeValue.valid())
			member.buttonSize = buttonSizeValue;

		const BValue& alignValue = style->value(Value_Title_Align);
		if (alignValue.valid())
			member.titleAlign = alignValue;

		const BValue& spaceValue = style->value(Value_Title_Space);
		if (spaceValue.valid())
			member.titleSpace = spaceValue;

		const BValue& iconSizeValue = style->value(Value_Title_Icon_Size);
		if (iconSizeValue.valid())
			member.iconSize = iconSizeValue;

		BIcon* titleIcon = style->icon(Icon_Title);
		if (titleIcon)
			member.titleIcon = titleIcon;

		BIcon* closeIcon = style->icon(Icon_Title_Button_Close);
		if (closeIcon)
			member.closeIcon = closeIcon;

		BIcon* minIcon = style->icon(Icon_Title_Button_Min);
		if (minIcon)
			member.minIcon = minIcon;

		BIcon* maxIcon = style->icon(Icon_Title_Button_Max);
		if (maxIcon)
			member.maxIcon = maxIcon;

		BImage* titleImage = style->image(Image_Title);
		if (titleImage)
			member.titleImage = titleImage;

		member.dirty = true;
	}
}
void BMainWindow::resizeEvent(const BEvent& event)
{
	member.dirty = true;
}

void BMainWindow::freshEvent(const BEvent& event)
{
	if (member.dirty)
	{
		member.freshRects();
		member.dirty = false;
	}
}
void BMainWindow::paintEvent(const BEvent& event)
{
	BPainter painter(this);
	painter.drawBackground();
	painter.drawPerch();

	if (painter.setColor(Color_Title))
	{
		painter.fillRect(member.titleRect);
	}
	if (member.titleImage)
	{
		painter.drawImage(member.titleRect, member.titleImage);
	}

	if (this->title().size() && painter.setColor(Color_Title_Text))
	{
		if (member.tr_title.size())
			painter.drawText(member.textRect, member.tr_title);
		else
			painter.drawText(member.textRect, this->title());
	}

	painter.setLineSmooth(true);
	painter.setLineWidth(2);

	if (member.titleIcon)
	{
		BImage* image = member.titleIcon->image(State_Normal);
		if (image)
			painter.drawImage(member.iconRect, image);
	}
	if (member.closeIcon)
	{
		State state = State_Normal;
		if (member.closeHovered)
		{
			state = State_Hovered;
			if (member.pressed)
				state = State_Pressed;
		}
		BImage* image = member.closeIcon->image(state);
		if (image)
		{
			BRect imageRect = member.closeRect.align(Align_Center, image->size());
			painter.drawImage(imageRect, image);
		}
	}
	else
	{
		StyleRole colorRole = Color_Title_Button;
		if (member.closeHovered)
		{
			colorRole = Color_Title_Button_Hovered;
			if (member.pressed)
				colorRole = Color_Title_Button_Pressed;
		}
		if (painter.setColor(colorRole))
		{
			painter.fillRect(member.closeRect);
			painter.setColor(200, 200, 200);
			BRect lineRect = member.closeRect * 0.6;
			painter.drawLine(lineRect.leftTop(), lineRect.rightBottom());
			painter.drawLine(lineRect.leftBottom(), lineRect.rightTop());
		}
	}

	if (member.maxIcon)
	{
		State state = State_Normal;
		if (member.maxHovered)
		{
			state = State_Hovered;
			if (member.pressed)
				state = State_Pressed;
		}
		BImage* image = member.maxIcon->image(state);
		if (image)
		{
			BRect imageRect = member.maxRect.align(Align_Center, image->size());
			painter.drawImage(imageRect, image);
		}
	}
	else
	{
		StyleRole colorRole = Color_Title_Button;
		if (member.maxHovered)
		{
			colorRole = Color_Title_Button_Hovered;
			if (member.pressed)
				colorRole = Color_Title_Button_Pressed;
		}
		if (painter.setColor(colorRole))
		{
			painter.fillRect(member.maxRect);
			BRect maxRect = member.maxRect * 0.4;
			painter.setColor(200, 200, 200);
			painter.drawRect(maxRect);
		}
	}

	if (member.minIcon)
	{
		State state = State_Normal;
		if (member.minHovered)
		{
			state = State_Hovered;
			if (member.pressed)
				state = State_Pressed;
		}
		BImage* image = member.minIcon->image(state);
		if (image)
		{
			BRect minRect = member.minRect.align(Align_Bottom | Align_HCenter, image->size());
			painter.drawImage(minRect, image);
		}
	}
	else
	{
		StyleRole colorRole = Color_Title_Button;
		if (member.minHovered)
		{
			colorRole = Color_Title_Button_Hovered;
			if (member.pressed)
				colorRole = Color_Title_Button_Pressed;
		}
		if (painter.setColor(colorRole))
		{
			painter.fillRect(member.minRect);
			BRect minRect = member.minRect * 0.4;
			painter.setColor(200, 200, 200);
			painter.drawLine(minRect.leftBottom(), minRect.rightBottom());
		}
	}

	painter.drawBorder();
	painter.drawMargin();
}

void BMainWindow::mouseEnterEvent(const BMouseEvent& event)
{
	BWidget::mouseEnterEvent(event);
	member.titleHovered = false;
	member.closeHovered = false;
	member.pressed = false;
}
void BMainWindow::mouseLeaveEvent(const BMouseEvent& event)
{
	if (member.titleHovered || member.closeHovered)
	{
		this->setCursor(Cursor_Arraw);
		member.titleHovered = false;
		member.closeHovered = false;
		member.pressed = false;
		this->fresh();
	}
}

void BMainWindow::mousePressEvent(const BMouseEvent& event)
{
	BWidget::mousePressEvent(event);
	BPoint pos = event.pos();
	Button button = event.button();

	member.pressed = true;
	member.pressedPos = pos;

	member.mode = Resize_None;
	if (member.borderLeft.contain(pos))
		member.mode = Resize_Left;
	if (member.borderTop.contain(pos))
		member.mode = Resize_Top;
	if (member.borderRight.contain(pos))
		member.mode = Resize_Right;
	if (member.borderBottom.contain(pos))
		member.mode = Resize_Bottom;
	fresh();
}
void BMainWindow::mouseReleaseEvent(const BMouseEvent& event)
{
	BWidget::mouseReleaseEvent(event);
	member.pressed = false;
	fresh();
}
void BMainWindow::mouseMoveEvent(const BMouseEvent& event)
{
	BWidget::mouseMoveEvent(event);
	BPoint pos = event.pos();
	//this->setCursor(Cursor_Arraw);
	BRect rect = member.borderLeft;
	if (member.borderLeft.contain(pos) || member.borderRight.contain(pos))
	{
		this->setCursor(Cursor_SizeHor);
	}
	if(member.borderTop.contain(pos) || member.borderBottom.contain(pos))
	{
		this->setCursor(Cursor_SizeVer);
	}
	if (member.pressed && member.mode)
	{
		BPoint offset = pos - member.pressedPos;
		BRect rect = this->rect();
		if (member.mode == Resize_Left)
		{
			rect.left() = rect.left() + offset.x();
			pos -= offset;
		}
		if (member.mode == Resize_Top)
		{
			rect.top() = (rect.top() + offset.y());
			pos -= offset;
		}
		if (member.mode == Resize_Right)
			rect.right() = (rect.right() + offset.x());
		if (member.mode == Resize_Bottom)
			rect.bottom() = (rect.bottom() + offset.y());
		this->setRect(rect);
		member.pressedPos = pos;
		return;
	}
	if (member.pressed && member.titleHovered)
	{
		BPoint offset = pos - member.pressedPos;
		this->move(offset);
		return;
	}
	bool titleHovered = member.titleRect.contain(pos);
	if (member.titleHovered != titleHovered)
	{
		member.titleHovered = titleHovered;
		this->fresh();
	}
	bool closeHovered = member.closeRect.contain(pos);
	if (member.closeHovered != closeHovered)
	{
		member.closeHovered = closeHovered;
		this->fresh();
	}
	bool minHovered = member.minRect.contain(pos);
	if (member.minHovered != minHovered)
	{
		member.minHovered = minHovered;
		this->fresh();
	}
	bool maxHovered = member.maxRect.contain(pos);
	if (member.maxHovered != maxHovered)
	{
		member.maxHovered = maxHovered;
		this->fresh();
	}
}

void BMainWindow::mouseClickEvent(const BMouseEvent& event)
{
	BWidget::mouseClickEvent(event);
	BPoint pos = event.pos();
	if (member.closeRect.contain(pos))
	{
		if (widget_member(this)->window)
		{
			this->close();
		}
		if (widget_member(this)->display)
		{
			this->hide();
		}
	}
	
	if (widget_member(this)->window)
	{
		if (member.minRect.contain(pos))
		{
			widget_member(this)->window->showMininum();
		}
		if (member.maxRect.contain(pos))
		{
			if (widget_member(this)->window->isMaxinumed())
				widget_member(this)->window->showNormal();
			else
				widget_member(this)->window->showMaxinum();
		}
	}

	if (widget_member(this)->display)
	{
		if (member.minRect.contain(pos))
		{
			this->hide();
		}
		if (member.maxRect.contain(pos))
		{
			BSize size = widget_member(this)->display->size();
			if (this->width() > size.width() * 0.96 && this->height() > size.height() * 0.96)
			{
				this->setRect(member.normalRect);
			}
			else
			{
				member.normalRect = this->rect();
				this->setRect(0, 0, size.width(), size.height());
			}
		}
	}
}
void BMainWindow::mouseDoubleClickEvent(const BMouseEvent& event)
{
	BPoint pos = event.pos();
	Button button = event.button();
	if (button == Button_Left && member.titleRect.contain(pos))
	{
		IWindow* window = widget_member(this)->window;
		if (window)
		{
			if (window->isMaxinumed())
				window->showNormal();
			else
				window->showMaxinum();
		}
		BDisplay* display = widget_member(this)->display;
		if (display)
		{
			BSize size = display->size();
			if (this->width() > size.width() * 0.96 && this->height() > size.height() * 0.96)
			{
				this->setRect(member.normalRect);
			}
			else
			{
				member.normalRect = this->rect();
				this->setRect(0, 0, size.width(), size.height());
			}
		}
		member.dirty = true;
		this->fresh();
	}
}

